package com.neusoft.neuiotms.dcom.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.bizcore.web.utils.EasyPoiStylerColorImpl;
import com.neusoft.neuiotms.dcom.constants.DCOMConstants;
import com.neusoft.neuiotms.dcom.converter.MaintainRuleConverter;
import com.neusoft.neuiotms.dcom.converter.MaintainTaskConverter;
import com.neusoft.neuiotms.dcom.dto.CMDBInstanceDTO;
import com.neusoft.neuiotms.dcom.dto.MaintainRuleDTO;
import com.neusoft.neuiotms.dcom.dto.MaintainTaskDTO;
import com.neusoft.neuiotms.dcom.model.MaintainRule;
import com.neusoft.neuiotms.dcom.model.MaintainTask;
import com.neusoft.neuiotms.dcom.model.enums.MaintainRuleStatus;
import com.neusoft.neuiotms.dcom.model.enums.MaintainTaskSourceEnum;
import com.neusoft.neuiotms.dcom.repository.MaintainRuleRepository;
import com.neusoft.neuiotms.dcom.repository.MaintainTaskRepository;
import com.neusoft.neuiotms.dcom.service.MaintainTaskService;
import com.neusoft.neuiotms.dcom.util.SendingMessageDcom;
import com.neusoft.neuiotms.dcom.vo.MaintainTaskQueryExportVO;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import io.micrometer.core.instrument.util.StringUtils;

@Service
public class MaintainTaskServiceImpl implements MaintainTaskService {

    @Autowired
    private MaintainTaskRepository maintainTaskRepository;
    @Autowired
    private MaintainTaskConverter maintainTaskConventer;
    @Autowired
    private SendingMessageDcom sendingMessage;
    @Autowired
    private MaintainRuleRepository maintainRuleRepository;
    @Autowired
    private MaintainRuleConverter maintainRuleConventer;

    @Override
    public List<MaintainTaskDTO> findAll() {
        final List<MaintainTask> entity = this.maintainTaskRepository.findAll();
        final List<MaintainTaskDTO> dtos =
                this.maintainTaskConventer.toListDTO(entity);
        return dtos;
    }

    @Override
    public Page<MaintainTaskDTO> search(final Pageable pageable, final Searchable searchable) {
        final Page<MaintainTask> models = this.maintainTaskRepository.search(pageable, searchable);
        return this.maintainTaskConventer.toPageDTO(models);
    }

    @Override
    public List<MaintainTaskDTO> search(final Searchable searchable) {
        final List<MaintainTask> entity = this.maintainTaskRepository.search(searchable);
        final List<MaintainTaskDTO> dtos =
                this.maintainTaskConventer.toListDTO(entity);
        return dtos;
    }

    @Override
    @Transactional
    public MaintainTaskDTO create(final MaintainTaskDTO dto) {
        final MaintainTask model = this.maintainTaskConventer.toModel(dto);

        // 保存维护规则
        this.createRuleOrUpdateRule(dto, model, "create");

        this.maintainTaskRepository.save(model);

        if (dto.getSource().name().equals(MaintainTaskSourceEnum.temporary.name())) {
            this.sendMessage(model);
        }

        return this.maintainTaskConventer.toDTO(model);
    }

    private void createRuleOrUpdateRule(final MaintainTaskDTO dto, final MaintainTask model, final String flag) {
        if (dto.isCreateRule()) {
            final MaintainRuleDTO rDto = new MaintainRuleDTO();
            if (flag.equals("update")) {
                rDto.setId(dto.getRule().getId());
            }
            rDto.setName(dto.getName());
            rDto.setModelCode(dto.getModelCode());
            rDto.setModelName(dto.getModelName());
            rDto.setSuspendService(dto.isSuspendService());
            rDto.setQuantifyingTime(dto.getQuantifyingTime());
            rDto.setDescription(dto.getDescription());
            rDto.setStatus(MaintainRuleStatus.enable);
            rDto.setSource(dto.getRuleSource());

            final MaintainRule rule = this.maintainRuleConventer.toModel(rDto);
            this.maintainRuleRepository.save(rule);
            if (flag.equals("create")) {
                model.setRule(rule);
            }
        }
    }

    @Override
    @Transactional
    public MaintainTaskDTO update(final Long id, final MaintainTaskDTO dto) {
        MaintainTask model;
        try {
            model = this.maintainTaskRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        if (model != null) {
            dto.setId(model.getId());
        }

        // 避免toModel覆盖值
        boolean toCreate = false;
        if (dto.isCreateRule() && !model.isCreateRule()) {
            toCreate = true;
        }

        boolean toUpdate = false;
        if (dto.isCreateRule() && model.isCreateRule()) {
            toUpdate = true;
        }

        model = this.maintainTaskConventer.toModel(dto);

        if (toCreate) {
            // 保存维护规则
            this.createRuleOrUpdateRule(dto, model, "create");
        }

        if (toUpdate) {
            // 更新保存维护规则
            this.createRuleOrUpdateRule(dto, model, "update");
        }

        this.maintainTaskRepository.save(model);

        //        if (dto.getSource().name().equals(MaintainTaskSource.temporary.name())) {
        //            this.sendMessage(model);
        //        }

        return this.maintainTaskConventer.toDTO(model);
    }

    @Override
    public MaintainTaskDTO details(final Long id) {
        final MaintainTask model;
        try {
            model = this.maintainTaskRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
        return this.maintainTaskConventer.toDTO(model, false);
    }

    @Override
    public void delete(final Long id) {
        this.maintainTaskRepository.deleteById(id);
    }

    /**
     * 发送消息
     */
    private String sendMessage(final MaintainTask model) {
        //拼消息体
        final JSONObject notice = new JSONObject();
        try {
            String objsStr = "";
            if (StringUtils.isNotEmpty(model.getJsonObjs())) {
                final List<CMDBInstanceDTO> iList = JSON.parseArray(model.getJsonObjs(), CMDBInstanceDTO.class);
                if (CollectionUtils.isNotEmpty(iList)) {
                    final List<String> nameList =
                            iList.stream().map(p -> p.getName() + "(" + p.getCode() + ")").collect(Collectors.toList());
                    objsStr = Joiner.on(DCOMConstants.COMMA_SPILT).join(nameList);
                }
            }
            final StringBuffer content = new StringBuffer(DCOMConstants.YOU_MAINTAIN_TASK);
            notice.put("appCode", "DCOM");
            notice.put("title", DCOMConstants.TEMPORARY_MAINTAIN_TASK);
            notice.put("type", Arrays.asList("notice"));

            final JSONObject system = new JSONObject();
            system.put("noticeType", DCOMConstants.TEMPORARY_MAINTAIN_TASK);

            system.put("noticeRoute", "dcom_tmpMaintainTask");

            final JSONArray usernames = new JSONArray();
            usernames.add(model.getChargeUserCode());
            system.put("users", usernames);

            // 维护Content
            content.append(DCOMConstants.MAINTAIN_OBJECT).append(objsStr)
                    .append(DCOMConstants.MAINTAIN_RIGHT_MIDDLE_BRACKETS);
            system.put("content", content.toString());

            notice.put("system", system);
            this.sendingMessage.SendMsgToNotice(notice.toString());

        } catch (final Exception e) {
            e.printStackTrace();
        }

        return notice.toString();
    }

    @Override
    public Long getCount(final Searchable searchable) {
        return this.maintainTaskRepository.getCount(searchable);
    }

    @Override
    public Workbook downloadQuery(final Searchable searchable, final Pageable pageable) {
        final List<MaintainTask> models = this.maintainTaskRepository.search(searchable);
        final List<MaintainTaskQueryExportVO> list = new ArrayList<>(models.size() == 0 ? 1 : models.size());
        models.forEach(model -> {
            list.add(this.maintainTaskConventer.toMaintainTaskQueryVO(model));
        });
        final ExportParams param = new ExportParams(DCOMConstants.MAINTAIN_RESULT_EXPORT,
                DCOMConstants.MAINTAIN_RESULT_EXPORT, ExcelType.XSSF);
        param.setStyle(EasyPoiStylerColorImpl.class);

        return ExcelExportUtil.exportExcel(param, MaintainTaskQueryExportVO.class, list);
    }

}
